package com.example.common.aop;


import com.alibaba.fastjson.JSON;
import com.example.common.annotation.OperationLog;
import com.example.common.entity.Log;
import com.example.util.RequestHostUtil;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.OperatingSystem;
import eu.bitwalker.useragentutils.UserAgent;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author YanMing
 * @version 1.0.0
 * @Description TODO
 * @createTime 2021年08月30日 09:11:00
 */
public class LogAspect {
    /**
     * 当前版本
     */

    private String buildVersion;
    /**
     * 打包时间
     */

    private String buildTime;

    protected Log createLog(JoinPoint joinPoint, Log log){
        if(log == null){
            log = new Log();
        }
        // 获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        // 从获取RequestAttributes中获取HttpServletRequest的信息
        HttpServletRequest request = (HttpServletRequest) requestAttributes
                .resolveReference(RequestAttributes.REFERENCE_REQUEST);
        String ip = RequestHostUtil.getIpAddress(request);
        log.setIp(ip);
        log.setMac(RequestHostUtil.getMac(ip));


        log.setVersion(buildVersion+"."+buildTime);
        // 操作URI
        String uri = request.getRequestURI();
        log.setUri(uri);
        // 时间
        log.setTime(new Date());

        try {
            // 从切面织入点处通过反射机制获取织入点处的方法
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            // 获取切入点所在的方法
            Method method = signature.getMethod();
            // 获取操作注解
            OperationLog operationLog = method.getAnnotation(OperationLog.class);
            if (operationLog != null) {
                /**
                 * 操作模块
                 */
                log.setModule(operationLog.module());
                /**
                 * 操作类型
                 */
                log.setType(operationLog.type());
                /**
                 * 操作描述
                 */
                log.setDescribe(operationLog.describe());
            }else if(uri != null){
                String[] urlarr = uri.split("/");
                if(urlarr!=null && urlarr.length >= 2){
                    log.setModule(urlarr[urlarr.length-2]);
                    log.setType(urlarr[urlarr.length-1]);
                }

            }
            // 获取请求的类名
            String className = joinPoint.getTarget().getClass().getName();
            // 获取请求的方法名
            String methodName = method.getName();
            methodName = className + "." + methodName;
            // 请求方法
            log.setMethod(methodName);
        } catch (Exception e) {
            e.printStackTrace();
        }


        // 请求的参数
        Map<String, String> rtnMap = converMap(request.getParameterMap());
        // 将参数所在的数组转换成json
        String params = JSON.toJSONString(rtnMap);
        try {
            //Clob clobparams = new javax.sql.rowset.serial.SerialClob(params.toCharArray());
            // 请求参数
            log.setRequestParams(params);
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            //统一拦截（查询当前session是否存在user）(这里user会在每次登陆成功后，写入session)
            Object userid = request.getSession().getAttribute("SESSION_USER_ID");
            Object username = request.getSession().getAttribute("SESSION_USER_NAME");
            if( userid!=null && !StringUtils.isBlank(userid.toString())  && username!=null && !StringUtils.isBlank(username.toString())  ){
                log.setUserid(userid.toString());
                log.setUsername(username.toString());
            }else{
                //未登录
                if(rtnMap.get("username")!=null){
                    log.setUsername(rtnMap.get("username"));
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }



        //获取浏览器信息
        String agent=request.getHeader("User-Agent");
        //"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36"
        //解析agent字符串
        UserAgent userAgent = UserAgent.parseUserAgentString(agent);
        //获取浏览器对象
        Browser browser = userAgent.getBrowser();
        //获取操作系统对象
        OperatingSystem operatingSystem = userAgent.getOperatingSystem();

        /**
         * 浏览器
         */
        log.setBrowserAgent(agent);
        /**
         * 浏览器名称
         */
        log.setBrowserName(browser.getName());
        /**
         * 浏览器版本
         */
        log.setBrowserVersion(userAgent.getBrowserVersion().toString());

        /**
         * 操作系统名
         */
        log.setSystemName(operatingSystem.getName());




        /**
         *         System.out.println("浏览器名:"+browser.getName());
         *         System.out.println("浏览器类型:"+browser.getBrowserType());
         *         System.out.println("浏览器家族:"+browser.getGroup());
         *         System.out.println("浏览器使用的渲染引擎:"+browser.getRenderingEngine());
         *         System.out.println("浏览器版本:"+userAgent.getBrowserVersion());
         *
         *         System.out.println("操作系统名:"+operatingSystem.getName());
         *         System.out.println("访问设备类型:"+operatingSystem.getDeviceType());
         *         System.out.println("操作系统家族:"+operatingSystem.getGroup());
         *         System.out.println("操作系统生产厂商:"+operatingSystem.getManufacturer());
         * request.getLocalAddr();//获取本地IP，即服务器IP
         * request.getLocalName();//获取本地名称，即服务器名称
         * request.getLocalPort();//获取本地端口号，即Tomcat端口号
         * request.getLocale();//用户的语言环境
         * request.getContextPath();//context路径
         * request.getMethod();//GET还是POST
         * request.getProtocol();//协议，http协议
         * request.getQueryString();//查询字符串
         * request.getRemoteAddr();//远程IP，即客户端IP
         * request.getRemotePort();//远程端口，即客户端端口
         * request.getRemoteUser();//远程用户
         * request.getRequestedSessionId();//客户端的Session的ID
         * request.getRequestURI();//用户请求的URL
         * request.getScheme();//协议头，例如http
         * request.getServerName();//服务器名称
         * request.getServerPort();//服务器端口
         * request.getServletPath();//Servlet路径
         */

        return log;
    }


   /**
    * 转换request 请求参数
    *
    * @param paramMap request获取的参数数组
    */
    public Map<String, String> converMap(Map<String, String[]> paramMap) {
        Map<String, String> rtnMap = new HashMap<String, String>();
        for (String key : paramMap.keySet()) {
            rtnMap.put(key, paramMap.get(key)[0]);
        }
        return rtnMap;
    }

    /**
     * 转换异常信息为字符串
     *
     * @param exceptionName    异常名称
     * @param exceptionMessage 异常信息
     * @param elements         堆栈信息
     */
    public String stackTraceToString(String exceptionName, String exceptionMessage, StackTraceElement[] elements) {
        StringBuffer strbuff = new StringBuffer();
        for (StackTraceElement stet : elements) {
            strbuff.append(stet + "\n");
        }
        String message = exceptionName + ":" + exceptionMessage + "\n\t" + strbuff.toString();
        return message;
    }
}
